---
title: Annotation Plugin
description: Enable users to create, edit, and delete various types of annotations like highlights, ink drawings, and shapes in Vue.
searchable: true
---

# Annotation Plugin

The Annotation Plugin provides a comprehensive framework for adding, editing, and managing annotations within a PDF document. It supports a wide range of common annotation types, including text markups (highlight, underline), free-hand drawings (ink), shapes (squares, circles), and more.

The plugin is built on an extensible "Tool" system, allowing you to define and customize different annotation behaviors and appearances.

## Installation

This plugin has several dependencies that must be installed to handle user interactions and manage state. The `history` plugin is optional but recommended for undo/redo functionality.

```sh npm2yarn
npm install @embedpdf/plugin-annotation @embedpdf/plugin-interaction-manager @embedpdf/plugin-selection @embedpdf/plugin-history
````

## Registration

Import `AnnotationPluginPackage` and its dependencies. It is crucial to register the dependencies *before* the annotation plugin itself.

```typescript {7, 20-23}
import { createPluginRegistration } from '@embedpdf/core'
import { EmbedPDF } from '@embedpdf/core/vue'
// ... other imports
import { InteractionManagerPluginPackage } from '@embedpdf/plugin-interaction-manager/vue'
import { SelectionPluginPackage } from '@embedpdf/plugin-selection/vue'
import { HistoryPluginPackage } from '@embedpdf/plugin-history/vue'
import { AnnotationPluginPackage } from '@embedpdf/plugin-annotation/vue'

const plugins = [
  // ... other essential plugins
  createPluginRegistration(LoaderPluginPackage, { /* ... */ }),
  createPluginRegistration(RenderPluginPackage),

  // Register dependencies first
  createPluginRegistration(InteractionManagerPluginPackage),
  createPluginRegistration(SelectionPluginPackage),
  createPluginRegistration(HistoryPluginPackage),

  // Register and configure the annotation plugin
  createPluginRegistration(AnnotationPluginPackage, {
    // Optional: Set the author name for created annotations
    annotationAuthor: 'Jane Doe',
  }),
]
```

## Usage

The plugin works by combining a UI component to render the annotations with a composable to manage the annotation tools and state.

### 1\. The `<AnnotationLayer />` Component

This component is responsible for rendering all annotations and handling user interactions like creating, selecting, moving, and resizing. It must be placed inside the `<Scroller />`'s default slot and wrapped by a `<PagePointerProvider>` to correctly process pointer events.

```vue {3, 17-23}
<script setup lang="ts">
import { PagePointerProvider } from '@embedpdf/plugin-interaction-manager/vue';
import { AnnotationLayer } from '@embedpdf/plugin-annotation/vue';
</script>
<template>
  <Scroller>
    <template #default="{ page }">
      <PagePointerProvider
        :page-index="page.pageIndex"
        :page-width="page.width"
        :page-height="page.height"
        :rotation="page.rotation"
        :scale="page.scale"
      >
        <RenderLayer :page-index="page.pageIndex" :scale="page.scale" style="pointer-events: none" />
        <SelectionLayer :page-index="page.pageIndex" :scale="page.scale" style="pointer-events: none" />
        <AnnotationLayer
          :page-index="page.pageIndex"
          :scale="page.scale"
          :page-width="page.width"
          :page-height="page.height"
          :rotation="page.rotation"
        />
      </PagePointerProvider>
    </template>
  </Scroller>
</template>
```

### 2\. Building an Annotation Toolbar

The `useAnnotationCapability` composable provides all the necessary methods to control the plugin. You can build a toolbar that allows users to select an "active tool" (like a pen or highlighter) and perform actions like deleting a selected annotation.

```vue
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { useAnnotationCapability } from '@embedpdf/plugin-annotation/vue';

const { provides: annotationApi } = useAnnotationCapability();
const activeTool = ref<string | null>(null);
const canDelete = ref(false);

let unsub1: () => void;
let unsub2: () => void;

onMounted(() => {
  if (!annotationApi.value) return;
  unsub1 = annotationApi.value.onActiveToolChange(tool => (activeTool.value = tool?.id ?? null));
  unsub2 = annotationApi.value.onStateChange(state => (canDelete.value = !!state.selectedUid));
});

onUnmounted(() => {
  unsub1?.();
  unsub2?.();
});

const setActiveTool = (toolId: string) => {
  annotationApi.value?.setActiveTool(activeTool.value === toolId ? null : toolId);
}
</script>
<template>
  <div>
    <button @click="setActiveTool('highlight')">Highlighter</button>
    <button @click="setActiveTool('ink')">Pen</button>
  </div>
</template>
```

### 3\. Creating Custom Tools

You can extend the plugin's functionality by adding your own tools. For example, you could create a custom image stamp. This is done by calling `addTool` on the plugin's capability, often within the `@initialized` event handler of the `<EmbedPDF>` component.

```vue
<script setup lang="ts">
import type { PluginRegistry } from '@embedpdf/core';
import { AnnotationPlugin, type AnnotationTool } from '@embedpdf/plugin-annotation/vue';
import { PdfAnnotationSubtype, type PdfStampAnnoObject } from '@embedpdf/models';

const handleInitialized = (registry: PluginRegistry) => {
  const annotationApi = registry.getPlugin<AnnotationPlugin>('annotation')?.provides();
  annotationApi?.addTool<AnnotationTool<PdfStampAnnoObject>>({
    id: 'stampApproved',
    name: 'Approved Stamp',
    interaction: { exclusive: false, cursor: 'copy' },
    matchScore: () => 0, // Doesn't match existing annotations
    defaults: {
      type: PdfAnnotationSubtype.STAMP,
      imageSrc: '/images/approved-stamp.png', // URL to your stamp image
    },
  });
};
</script>
<template>
  <EmbedPDF :engine="engine" :plugins="plugins" @initialized="handleInitialized">
  </EmbedPDF>
</template>
```

## Live Example

The example below includes a toolbar for selecting different annotation tools (highlight, ink pen, square) and a delete button that becomes active when an annotation is selected.

import { AnnotationExample } from '../code-examples/annotation-example';

<AnnotationExample />

## API Reference

### Configuration (`AnnotationPluginConfig`)

| Option | Type | Description |
| :--- | :--- | :--- |
| **`annotationAuthor`** | `string` | Sets the author name for all created annotations. **Default**: `'Guest'` |
| **`autoCommit`** | `boolean` | If `true`, annotation changes are automatically saved to the engine. **Default**: `true` |
| **`tools`** | `AnnotationTool[]` | An array of custom annotation tools to add or override default tools. |
| **`colorPresets`** | `string[]` | A list of hex color strings to be used in a color picker UI. |
| **`deactivateToolAfterCreate`** | `boolean` | If `true`, the active tool is deselected after an annotation is created. **Default**: `false` |
| **`selectAfterCreate`** | `boolean` | If `true`, a newly created annotation is automatically selected. **Default**: `true` |

### Component: `<AnnotationLayer />`

The primary component for rendering and interacting with annotations.

| Prop | Type | Description |
| :--- | :--- | :--- |
| **`pageIndex`** | `number` | **(Required)** The page index this layer corresponds to. |
| **`scale`** | `number` | **(Required)** The current zoom scale of the page. |
| **`rotation`** | `number` | **(Required)** The current rotation of the page. |
| **`pageWidth`** | `number` | **(Required)** The unscaled width of the PDF page. |
| **`pageHeight`** | `number` | **(Required)** The unscaled height of the PDF page. |
| **`selectionOutlineColor`**| `string` | The color of the outline around a selected annotation. **Default**: `'#007ACC'` |

### Scoped Slot: `selection-menu`

The `<AnnotationLayer>` provides a scoped slot to render a custom menu when an annotation is selected.

| Prop | Type | Description |
| :--- | :--- | :--- |
| `item` | `RedactionItem` | The selected annotation data. |
| `selected` | `boolean` | `true` if an annotation is currently selected. |
| `menuWrapperProps` | `object` | Vue props to bind to your menu's wrapper element for positioning. |
| `rect` | `Rect` | The bounding box of the selected annotation. |

### Composable: `useAnnotationCapability()`

Connects your components to the annotation plugin's state and methods.

#### Returns

| Property | Type | Description |
| :--- | :--- | :--- |
| **`provides`** | `Ref<AnnotationCapability \| null>` | A ref object with methods to control the plugin, or `null` if not ready. |

#### `AnnotationCapability` Methods

A selection of key methods available on the `provides.value` object:

| Method | Description |
| :--- | :--- |
| **`setActiveTool(toolId)`** | Activates an annotation tool (e.g., `'ink'`, `'highlight'`). Pass `null` to deactivate. |
| **`getActiveTool()`** | Returns the currently active `AnnotationTool` object, or `null`. |
| **`addTool(tool)`** | Registers a new custom `AnnotationTool`. |
| **`deleteAnnotation(..)`** | Deletes an annotation from a page. |
| **`getSelectedAnnotation()`** | Returns the currently selected `TrackedAnnotation` object, or `null`. |
| **`onStateChange(cb)`** | Subscribes to any change in the annotation state. Returns an `unsubscribe` function. |
| **`onAnnotationEvent(cb)`**| Subscribes to events like annotation creation, updates, or deletion. Returns an `unsubscribe` function. |